let rec exist x list =
  match list with
      [] -> false
      | e::l when e=x -> true   
      | e::l -> exist x l;;

let rec add_list x list =
  match list with
      [] -> []
    | e::l when e < x -> e:: add_list x l
    | e::l when e=x -> list
    | e::l -> x::e::l;;

let rec remove_list x list =
  match list with
      [] -> []
    | e::l when e=x -> l
    | e::l -> remove_list x l;;
(*
let rec map f list =
  match list with
      [] -> []
    | e::l -> f e :: map f list;;
*)
let map f list = [];;

let rec iter f list =
  match list with
      [] -> ()
    |e::l -> f e;
             iter f l;;

let rec for_all f list =
  match list with 
      [] -> true
    | e::l ->  f e && for_all f l;;

let fpair x = x mod 2 = 0;;


let upper_case x =
  let ascii = int_of_char x in
  match ascii with
    ascii when ascii < int_of_char 'a' -> x
    | ascii when ascii <= int_of_char 'z' -> char_of_int (ascii - (int_of_char 'a' - int_of_char 'A'))
    | ascii -> x;; 


let lower_case x =
  let ascii = int_of_char x in
  match ascii with
    ascii when ascii < int_of_char 'A' -> x
    | ascii when ascii <= int_of_char 'Z' -> char_of_int (ascii + (int_of_char 'a' - int_of_char 'A'))
    | ascii -> x;;

let string_of_char c = String.make 1 c;;

let string_apply f str = 
  let longueur = String.length str in
  let rec calcul i  = 
    match i with 
	i when i = longueur - 1 -> string_of_char (f ( str.[longueur - 1]))
      | i -> (string_of_char (f str.[i])) ^ calcul (i+1) in 
  calcul 0 ;;

let string_uppercase str = string_apply (upper_case) str;;

let string_lowercase str = string_apply (lower_case) str;;

let convert_first_maj str = 
  let longueur = String.length str in
  let rec calcul i  = 
    match i with 
        0 -> (string_of_char (upper_case (str.[0]))) ^ calcul (i+1)
      | i when i = longueur - 1 -> string_of_char (lower_case str.[longueur - 1])
      | i -> (string_of_char(lower_case str.[i])) ^ calcul (i+1) in 
  calcul 0 ;;

let create_contact (nom, age, adress, telephone) = ((convert_first_maj nom), age, adress, telephone);;

let manage_contact f contact agenda = f contact agenda;;

let rec add_contact (nom, age, adress, telephone)  agenda =
  let (nom2, age2, adress2, telephone2) = create_contact (nom, age, adress, telephone) in
      match agenda with
	  [] -> []
	| (nom3, age3, adress3, telephone3) ::l when nom2 < nom3 ->  (nom3, age3, adress3, telephone3):: add_contact (nom, age, adress, telephone) l
        | (nom3, age3, adress3, telephone3) ::l when nom2 = nom3 -> invalid_arg "Ce contact existe deja"
	| (nom3, age3, adress3, telephone3) ::l -> (nom2, age2, adress2, telephone2):: (nom3, age3, adress3, telephone3):: l;;

let rec remove_contact contact  agenda =
      match agenda with
      [] -> [] 
	| e ::l when e = contact -> l  
        | e ::l -> remove_contact contact l;;

let rec edit_contact nom (nom2, age2, adress2, telephone2) agenda =
      match agenda with
      [] -> [] 
	| (nom3, _, _ , _)::l when nom3 = nom ->  (nom2, age2, adress2, telephone2)::l
	| e::l -> e:: edit_contact nom (nom2, age2, adress2, telephone2) l;;

let rec is_good_format f agenda = 
  for_all f agenda;;

let rec print_agenda agenda = 
  match agenda with 
      [] -> ()
    | (nom, age, adress, telephone)::l -> print_string "Nom: ";
                                          print_string nom;
                                          print_newline () ;
					  print_string "Age: ";
					  print_int age;
					  print_newline ();
					  print_string "Adresse: ";
					  print_string adress;
					  print_newline ();
					  print_string "Telephone: ";
					  print_int telephone;
					  print_newline ();
					  print_agenda l;;

